<template>
  <div>
    <div class="boxMap" :style="{ height: configure?.height || '400px', width: configure?.width || '100%' }">
      <div id="r-result" v-if="mapType == 'opt'">
        <input type="text" id="suggestId" size="30" value="" placeholder="搜索位置" class="ipt" />
      </div>
      <div id="searchResultPanel" style="border: 1px solid #c0c0c0; width: 300px; max-height: 200px; display: none"></div>
      <div :style="{ height: configure?.height || '400px', width: configure?.width || '100%' }" id="container"></div>
    </div>
  </div>
</template>

<script setup lang="ts">
import { onMounted, ref, shallowRef, watch } from "vue";
import { loadBMap } from "./index";
import { MapOptions, MapType } from "./type";
type T = any;
const map = shallowRef();
const emits = defineEmits<{
  (e: "update:modelValue", val: MapType): void;
  (e: "onChange", val: any): void;
}>();
const defaultPoint: MapType[] = [{ lat: 30.52, lng: 114.31 }];
const props = defineProps<{
  modelValue: MapType[] | MapType;
  configure: MapOptions;
}>()
const pointValue = shallowRef();
const mapType = ref(props.configure.type)
const mapZoom = ref(props.configure.zoom || 15)
onMounted(async () => {
  await loadBMap(props.configure.mapKey || '');
  init();
})

// 检查地图初始值
const checkMapValue = (val: any): MapType[] => {

  if (!(val instanceof Array)) {
    if (typeof val == "object" && val?.lat && val.lng) {
      if (typeof val?.lat == 'string') {
        val.lat = Number(val?.lat)
      }
      if (typeof val?.lng == 'string') {
        val.lng = Number(val?.lng)
      }
      return [val];
    }
    return defaultPoint;
  } else {
    return (!val || !val.length ? defaultPoint : val) as MapType[];
  }
};
const mapPoint = ref(checkMapValue(props.modelValue));
// 初始化搜索控件
const initSearchContorl = () => {
  let value = "";
  let myValue = "";
  var ac = new (window as T).BMap.Autocomplete({
    //建立一个自动完成的对象
    "input": "suggestId",
    "location": map.value,
  });

  ac.addEventListener("onhighlight", function (e: any) {
    //鼠标放在下拉列表上的事件
    var _value = e.fromitem.value;
    if (e.fromitem.index > -1) {
      value =
        _value.province + _value.city + _value.district + _value.street + _value.business;
    }
  });

  ac.addEventListener("onconfirm", function (e: any) {
    //鼠标点击下拉列表后的事件
    var _value = e.item.value;
    myValue = _value.province + _value.city + _value.district + _value.street + _value.business;
    map.value.clearOverlays();
    function myFun() {
      var pp = local.getResults().getPoi(0).point;
      // 抛出结果更改为数组
      emits("update:modelValue", pp);
      emits("onChange", pp);
      mapPoint.value = [pp]
      map.value.centerAndZoom(pp, mapZoom.value);
      map.value.addOverlay(new (window as T).BMap.Marker(pp)); //添加标注
    }

    var local = new (window as T).BMap.LocalSearch(map.value, {
      onSearchComplete: myFun,
    });
    local.search(myValue);
  });
};
// 创建标注
const createMarker = (pointData: MapType) => {
  const point = new (window as T).BMap.Point(
    pointData.lng,
    pointData.lat
  );
  return new (window as T).BMap.Marker(point);
}
// 初始化地图
const init = () => {

  if (!map.value && (window as T).BMap) {
    // 初始化地图
    map.value = new (window as T).BMap.Map('container');
    // 渲染地图控件
    const top_left_control = new (window as T).BMap.NavigationControl({ anchor: (window as T).BMAP_ANCHOR_TOP_LEFT, type: (window as T).BMAP_NAVIGATION_CONTROL_PAN });  //左上角，添加默认缩放平移控件
    const top_left_navigation = new (window as T).BMap.NavigationControl({ anchor: (window as T).BMAP_ANCHOR_TOP_LEFT });  //左上角，添加默认缩放平移控
    map.value.addControl(top_left_control);
    map.value.addControl(top_left_navigation);
    if (mapType.value == "opt") {
      initSearchContorl()
    }
  }
  if (props.configure.type == 'opt') {
    initMapClick()
  }

  // 设置中心点
  const centerPoint = mapPoint.value instanceof Array ? mapPoint.value[0] : mapPoint.value
  pointValue.value = new (window as T).BMap.Point(centerPoint.lng, centerPoint.lat);
  map.value.centerAndZoom(pointValue.value, mapZoom.value);
  // add 1000m² Overlay
  // const circle = new (window as T).BMap.Circle(pointValue.value, 3000, { enableMassClear: false, fillColor: "#236cff", strokeWeight: 1, fillOpacity: 0.1, strokeOpacity: 0.5 });
  // map.value.addOverlay(circle);
  // set center marker
  const home = new (window as T).BMap.Marker(pointValue.value, {
    enableMassClear: true,
    title: '',
  })
  map.value.addOverlay(home);

  // 设置开始和结束的标注点位

  if (mapPoint.value.length) {
    // 第一个标注
    map.value.addOverlay(createMarker(mapPoint.value[0]));
    if (mapPoint.value.length >= 2) {
      // 最后一个标注
      map.value.addOverlay(createMarker(mapPoint.value[mapPoint.value.length - 1]));
    }
  }

  // 添加线
  const bounds = new (window as T).BMap.Bounds();
  (mapPoint.value)?.forEach(coord => {
    bounds.extend(new (window as T).BMap.Point(coord.lng, coord.lat));
  });
  map.value.setViewport(bounds);
  const polylinePoints = mapPoint.value.map(coord => new (window as T).BMap.Point(coord.lng, coord.lat));
  const polyline = new (window as T).BMap.Polyline(polylinePoints, { strokeColor: "blue", strokeWeight: 4, strokeOpacity: 0.7 });
  map.value.addOverlay(polyline);
  emits("update:modelValue", mapPoint.value[0]);
  emits("onChange", mapPoint.value[0]);
  map.value.addEventListener('zoomend', function () {
    mapZoom.value = map.value.getZoom();
  })
}
const initMapClick = () => {
  map.value.addEventListener('click', function (e: { point: { lng: string; lat: string; }; }) {
    map.value.clearOverlays()
    const marker = createMarker({ lat: e.point.lat, lng: e.point.lng })
    emits("update:modelValue", { lat: e.point.lat, lng: e.point.lng });
    emits("onChange", { lat: e.point.lat, lng: e.point.lng });
    map.value.addOverlay(marker);
  });
}
watch(() => props.modelValue, (val) => {
  // 检测地图数据
  mapPoint.value = checkMapValue(val)
  if (mapPoint.value.length >= 2) {
    mapType.value = 'preview'
  }
  // 当地图存在时，重新设置中心点和标注;
  if (map.value) {
    map.value.clearOverlays()
    if (mapPoint.value instanceof Array) {
      if (mapPoint.value.length) {
        // 第一个标注
        const point = new (window as T).BMap.Point(mapPoint.value[0].lng, mapPoint.value[0].lat);
        map.value.centerAndZoom(point, mapZoom.value);
        map.value.addOverlay(createMarker(mapPoint.value[0]));
        map.value.setCenter(point)
        if (mapPoint.value.length >= 2) {
          // 最后一个标注
          map.value.addOverlay(createMarker(mapPoint.value[mapPoint.value.length - 1]));
          const bounds = new (window as T).BMap.Bounds();
          (mapPoint.value)?.forEach(coord => {
            bounds.extend(new (window as T).BMap.Point(coord.lng, coord.lat));
          });
          map.value.setViewport(bounds);
          const polylinePoints = mapPoint.value.map(coord => new (window as T).BMap.Point(coord.lng, coord.lat));
          const polyline = new (window as T).BMap.Polyline(polylinePoints, { strokeColor: "blue", strokeWeight: 4, strokeOpacity: 0.7 });
          map.value.addOverlay(polyline);
        }
      }
    } else {
      const centerPoint = mapPoint.value as MapType
      const point = new (window as T).BMap.Point(centerPoint.lng, centerPoint.lat);
      map.value.centerAndZoom(point, mapZoom.value);
      const mainMarker = new (window as T).BMap.Marker(point, {
        enableMassClear: true,
        title: '',
      })
      map.value.setCenter(point)
      map.value.addOverlay(mainMarker);
    }

  }
})
watch(() => props.configure.type, (val) => {
  mapType.value = val
})
</script>

<style scoped lang="scss">
.boxMap {
  position: relative;

  .ipt {
    top: 12px;
    right: 0;
    position: absolute;
    z-index: 10;
    width: 250px;
    outline: none;
    border-radius: 12px;
    border: 1px solid #bbb;
    text-indent: 0.5rem;
    height: 20px;
    padding-right: 20px;
  }
}
</style>

<style>
.BMap_cpyCtrl {
  display: none !important;
}

.anchorBL {
  display: none !important;
}
</style>